import os

from django.shortcuts import render
from openai import OpenAI
from rest_framework.response import Response
from rest_framework.views import APIView

from utils.qwen_chatbot import QwenChatBot


# Create your views here.


class QaTestApiView(APIView):
    """

    ##角色定位
    你是一个专业的招聘顾问,精通企业招聘流程,面试技巧,人力资源专业知识
    ##核心任务
    1. 接收用户在Boss直聘平台的提问（用户身份可能是企业HR或求职者），先判断用户身份及问题场景，再针对性解答；
    2. 若用户问题涉及平台功能（如“如何发布职位”“怎么查看简历联系方式”），需按平台最新规则（以企业/求职者端实际操作路径为准）分步说明；
    3. 若用户问题涉及招聘技巧（如“HR如何筛选销售简历”“求职者怎么写简历亮点”），需提供可落地的方法，避免空泛建议；
    4. 若用户问题涉及政策/法规（如“试用期工资标准”“劳动合同签订要求”），需明确标注“内容仅供参考，具体以当地劳动部门规定为准”，避免法律风险。
    ### 场景规则
    - 拒绝回答与Boss直聘招聘场景无关的问题（如生活常识、娱乐八卦等），若用户提问偏离，需礼貌引导：“抱歉，目前仅能解答Boss直聘平台相关的招聘/求职问题，你可以说说具体的招聘需求或求职疑问哦～”；
    - 回答需简洁聚焦，避免冗余：HR类问题侧重“效率/合规”，求职者类问题侧重“实用/落地”；
    - 若用户问题模糊（如“怎么找工作”），需先追问关键信息：“为了更精准帮你，想了解你目前的求职方向（如行业/岗位），或是否在Boss直聘遇到了具体操作问题呀？”

    ### 输出要求
    1. 语言风格：口语化但专业，避免生硬术语（如解释“五险一金”时，可补充“即养老保险、医疗保险、失业保险、工伤保险、生育保险及住房公积金”）；
    2. 结构清晰：复杂问题（如操作类）用“步骤”呈现，多维度问题（如简历优化）用“要点”拆分；
    3. 优先级：先给结论/核心方法，再补充细节，确保用户快速获取关键信息。

    ### 用户当前问题:
    {question}
    """

    def post(self, request):
        question = request.data.get('question')
        if not question:
            return Response({"code": 0, "message": "请输入问题"})
            # 初始化聊天机器人

        bot = QwenChatBot()
        result = bot.single_turn_chat(question)
        return Response({"code": 1, "message": "success", "data": result['answer']})


from django.http import StreamingHttpResponse
import json


class QaTest2ApiView(APIView):
    def post(self, request):
        question = request.data.get('question')
        if not question:
            return Response({"code": 0, "message": "请输入问题"})

        client = OpenAI(
            api_key=os.getenv("DASHSCOPE_API_KEY"),
            base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        )

        def generate():
            try:
                completion = client.chat.completions.create(
                    model="qwen-plus",
                    messages=[
                        {"role": "system", "content": "You are a helpful assistant."},
                        {"role": "user", "content": question},
                    ],
                    stream=True,
                    temperature=0.9,
                    stream_options={"include_usage": True}
                )

                for chunk in completion:
                    # 完整的错误检查
                    if chunk.choices and len(chunk.choices) > 0:
                        choice = chunk.choices[0]
                        # 检查 delta 属性是否存在
                        if hasattr(choice, 'delta') and choice.delta:
                            # 检查 content 是否存在
                            if hasattr(choice.delta, 'content') and choice.delta.content:
                                yield f"data: {json.dumps({'content': choice.delta.content})}\n\n"
                            # 可选：处理其他 delta 信息，如 role
                            # elif hasattr(choice.delta, 'role') and choice.delta.role:
                            #     yield f"data: {json.dumps({'role': choice.delta.role})}\n\n"
                        # 处理结束原因
                        elif hasattr(choice, 'finish_reason') and choice.finish_reason:
                            yield f"data: {json.dumps({'finish_reason': choice.finish_reason})}\n\n"
                    # 处理 usage 信息（如果需要）
                    # elif hasattr(chunk, 'usage') and chunk.usage:
                    #     usage_data = {
                    #         'prompt_tokens': chunk.usage.prompt_tokens,
                    #         'completion_tokens': chunk.usage.completion_tokens,
                    #         'total_tokens': chunk.usage.total_tokens
                    #     }
                    #     yield f"data: {json.dumps({'usage': usage_data})}\n\n"
            except Exception as e:
                yield f"data: {json.dumps({'error': str(e)})}\n\n"

        return StreamingHttpResponse(
            generate(),
            content_type='text/event-stream',
            headers={
                'Cache-Control': 'no-cache',
                'Connection': 'keep-alive',
            }
        )


import json
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.http import StreamingHttpResponse
from typing import Dict, Optional, List
from utils.thread_safe_chatbot import ThreadSafeChatBot, Message  # 导入工具类和模型
import os


class ChatGeneralView(APIView):
    """
    通用对话接口（支持单轮/多轮、非流式）
    核心：需传入完整对话历史 messages，工具类无状态处理
    """

    def post(self, request) -> Response:
        # 1. 解析请求参数
        req_data: Dict = request.data
        messages: Optional[List[Dict[str, str]]] = req_data.get("messages")  # 完整对话历史
        model: Optional[str] = req_data.get("model")  # 可选：指定模型（覆盖默认）
        temperature: float = req_data.get("temperature", 0.9)  # 生成温度（默认0.9）

        # 2. 参数校验
        if not messages:
            return Response(
                {"code": 400, "message": "缺少必填参数：messages（完整对话历史）"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 调用工具类通用 chat 方法（非流式）
        try:
            global_chatbot = ThreadSafeChatBot()
            # 工具类内部已做 messages 格式校验，此处直接调用
            answer = global_chatbot.chat(
                messages=messages,
                model=model,
                temperature=temperature,
                stream=False
            )

            # 4. 返回响应（含完整对话历史，方便前端更新上下文）
            return Response({
                "code": 200,
                "message": "success",
                "data": {
                    "answer": answer,
                    "updated_messages": messages + [{"role": "assistant", "content": answer}]  # 更新对话历史
                }
            })
        except ValueError as e:
            print(e)
            # 捕获参数格式错误（如 messages 格式不正确）
            return Response(
                {"code": 400, "message": f"参数错误：{str(e)}"},
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            print(e)
            # 捕获API调用等其他错误
            return Response(
                {"code": 500, "message": f"对话失败：{str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class ChatSingleTurnView(APIView):
    """
    单轮对话便捷接口（非流式）
    简化：无需手动构建 messages，仅需传入 question 和 system_prompt
    """

    def post(self, request) -> Response:
        # 1. 解析请求参数
        question: Optional[str] = request.data.get("question")  # 用户问题
        system_prompt: str = request.data.get("system_prompt", "You are a helpful assistant.")  # 系统提示词（默认）
        model: Optional[str] = request.data.get("model")
        temperature: float = request.data.get("temperature", 0.9)

        # 2. 参数校验
        if not question or not question.strip():
            return Response(
                {"code": 400, "message": "缺少必填参数：question（用户问题不能为空）"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 调用工具类单轮对话便捷方法
        try:
            global_chatbot = ThreadSafeChatBot()
            answer = global_chatbot.single_turn_chat(
                question=question,
                system_prompt=system_prompt,
                model=model,
                temperature=temperature
            )

            # 4. 返回响应（含自动构建的对话历史）
            return Response({
                "code": 200,
                "message": "success",
                "data": {
                    "answer": answer,
                    "full_messages": [
                        {"role": "system", "content": system_prompt},
                        {"role": "user", "content": question},
                        {"role": "assistant", "content": answer}
                    ]
                }
            })
        except Exception as e:
            return Response(
                {"code": 500, "message": f"单轮对话失败：{str(e)}"},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class ChatStreamGeneralView(APIView):
    """
    通用流式对话接口（支持单轮/多轮）
    核心：传入完整对话历史，返回 SSE 格式流式响应
    """

    def post(self, request) -> StreamingHttpResponse:
        # 1. 解析请求参数
        req_data: Dict = request.data
        messages: Optional[List[Dict[str, str]]] = req_data.get("messages")
        model: Optional[str] = req_data.get("model")
        temperature: float = req_data.get("temperature", 0.9)

        # 2. 前置参数校验（参数错误直接返回非流式响应）
        if not messages:
            return Response(
                {"code": 400, "message": "缺少必填参数：messages（完整对话历史）"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 定义流式生成器（适配 SSE 协议：data: {json}\n\n）
        def stream_generator() -> str:
            try:
                global_chatbot = ThreadSafeChatBot()
                # 调用工具类流式 chat 方法，获取生成器
                stream_chunks = global_chatbot.chat(
                    messages=messages,
                    model=model,
                    temperature=temperature,
                    stream=True
                )

                # 直接迭代处理流式响应
                for chunk in stream_chunks:
                    yield f"data: {chunk}\n\n"
            except ValueError as e:
                # 流式中捕获参数错误
                error_chunk = json.dumps({
                    "type": "error",
                    "data": f"参数错误：{str(e)}",
                    "complete": True
                })
                yield f"data: {error_chunk}\n\n"
            except Exception as e:
                # 流式中捕获其他错误
                error_chunk = json.dumps({
                    "type": "error",
                    "data": f"流式对话失败：{str(e)}",
                    "complete": True
                })
                yield f"data: {error_chunk}\n\n"

        # 4. 返回流式响应（设置 SSE 必要头信息）
        response = StreamingHttpResponse(
            stream_generator(),
            content_type="text/event-stream"  # SSE 标准 Content-Type
        )
        # 禁用缓存（避免浏览器缓存流式内容，导致重复接收）
        response["Cache-Control"] = "no-cache, no-store, must-revalidate"
        response["Pragma"] = "no-cache"
        response["Expires"] = "0"
        return response


class ChatStreamSingleTurnView(APIView):
    """
    流式单轮对话便捷接口
    简化：无需手动构建 messages，仅需传入 question 和 system_prompt
    """

    def post(self, request) -> StreamingHttpResponse:
        # 1. 解析请求参数
        question: Optional[str] = request.data.get("question")
        system_prompt: str = request.data.get("system_prompt", "You are a helpful assistant.")
        model: Optional[str] = request.data.get("model")
        temperature: float = request.data.get("temperature", 0.9)

        print(f"Received request - question: {question}")  # 调试信息

        # 2. 前置参数校验
        if not question or not question.strip():
            print("Question validation failed")  # 调试信息
            return Response(
                {"code": 400, "message": "缺少必填参数：question（用户问题不能为空）"},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 定义流式生成器
        def stream_generator() -> str:
            print("Stream generator started")  # 调试信息
            try:
                global_chatbot = ThreadSafeChatBot()
                print("Chatbot initialized")  # 调试信息
                stream_chunks = global_chatbot.stream_single_turn_chat(
                    question=question,
                    system_prompt=system_prompt,
                    model=model,
                    temperature=temperature
                )
                print("Stream chunks obtained")  # 调试信息

                for chunk in stream_chunks:
                    print(f"Sending chunk: {chunk}")  # 调试信息
                    # 直接发送chunk，保持SSE格式，发送的是已经格式化的JSON数据
                    yield f"data: {chunk}\n\n"
            except Exception as e:
                print(f"Stream error: {e}")  # 调试信息
                import traceback
                print(f"Traceback: {traceback.format_exc()}")  # 详细错误信息
                error_chunk = json.dumps({
                    "type": "error",
                    "data": f"流式单轮对话失败：{str(e)}",
                    "complete": True
                })
                yield f"data: {error_chunk}\n\n"

        print("Returning StreamingHttpResponse")  # 调试信息
        # 4. 返回流式响应
        response = StreamingHttpResponse(
            stream_generator(),
            content_type="text/event-stream"
        )
        response["Cache-Control"] = "no-cache, no-store, must-revalidate"
        response["Pragma"] = "no-cache"
        response["Expires"] = "0"
        return response


import time
import uuid
from datetime import datetime
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from utils.redis_utils import redis_client


class CreateChatView(APIView):
    """创建新对话接口"""

    def post(self, request):
        # 1. 获取参数
        user_id = request.data.get('user_id')
        init_title = request.data.get('init_title', '新对话')

        # 2. 参数校验
        if not user_id:
            return Response(
                {'error': 'user_id不能为空'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 生成唯一对话ID
        timestamp = int(time.time() * 1000)
        random_str = uuid.uuid4().hex[:2]
        chat_id = f"chat_{user_id}_{timestamp}_{random_str}"

        # 4. 存储对话基础信息（业务逻辑：定义键名和存储结构）
        now_ts = timestamp
        # 哈希结构：存储对话详情
        chat_info_key = f"chat:info:{chat_id}"
        redis_client.hset(chat_info_key, 'user_id', user_id)
        redis_client.hset(chat_info_key, 'title', init_title)
        redis_client.hset(chat_info_key, 'create_time', now_ts)
        redis_client.hset(chat_info_key, 'last_msg_time', now_ts)
        redis_client.hset(chat_info_key, 'status', 'active')
        redis_client.expire(chat_info_key, 30 * 24 * 3600)  # 30天过期

        # 有序集合：用户对话列表索引
        user_chat_key = f"chat:user:list:{user_id}"
        redis_client.zadd(user_chat_key, {chat_id: now_ts})
        redis_client.expire(user_chat_key, 30 * 24 * 3600)

        # 列表：对话消息ID存储
        chat_msgs_key = f"chat:msgs:{chat_id}"
        redis_client.rpush(chat_msgs_key, "")  # 初始化空列表
        redis_client.expire(chat_msgs_key, 30 * 24 * 3600)

        # 5. 返回结果
        return Response({
            'chat_id': chat_id,
            'title': init_title,
            'create_time': datetime.fromtimestamp(now_ts / 1000).strftime('%Y-%m-%d %H:%M:%S')
        })


class ChatListView(APIView):
    """获取对话列表接口"""

    def get(self, request):
        # 1. 获取参数
        user_id = request.query_params.get('user_id')
        page_num = int(request.query_params.get('page_num', 1))
        page_size = int(request.query_params.get('page_size', 10))

        # 2. 参数校验
        if not user_id:
            return Response(
                {'error': 'user_id不能为空'},
                status=status.HTTP_400_BAD_REQUEST
            )
        if page_size > 20:
            return Response(
                {'error': 'page_size最大为20'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 计算分页参数
        start = (page_num - 1) * page_size
        end = page_num * page_size - 1

        # 4. 查询用户对话列表（业务逻辑：定义键名和查询逻辑）
        user_chat_key = f"chat:user:list:{user_id}"
        # 获取分页的对话ID及分数（最后消息时间）
        chat_list = redis_client.zrevrange(
            user_chat_key,
            start,
            end,
            withscores=True
        )

        # 5. 组装对话详情
        result = []
        for chat_id, last_msg_ts in chat_list:
            # 查询对话基础信息
            chat_info_key = f"chat:info:{chat_id}"
            chat_info = redis_client.hgetall(chat_info_key)

            # 过滤已删除的对话
            if chat_info.get('status') != 'active':
                continue

            # 格式化时间
            create_time = datetime.fromtimestamp(
                chat_info.get('create_time', 0) / 1000
            ).strftime('%Y-%m-%d %H:%M:%S')

            last_msg_time = datetime.fromtimestamp(
                last_msg_ts / 1000
            ).strftime('%Y-%m-%d %H:%M:%S')

            result.append({
                'chat_id': chat_id,
                'title': chat_info.get('title', '未命名对话'),
                'create_time': create_time,
                'last_msg_time': last_msg_time
            })

        # 6. 获取总条数
        total = redis_client.zcard(user_chat_key)

        # 7. 返回结果
        return Response({
            'total': total,
            'page_num': page_num,
            'page_size': page_size,
            'chats': result
        })


class ChatDetailView(APIView):
    """获取对话详情接口"""

    def get(self, request, chat_id):
        # 1. 获取参数
        user_id = request.query_params.get('user_id')

        # 2. 参数校验
        if not user_id:
            return Response(
                {'error': 'user_id不能为空'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 验证对话归属权（业务逻辑：权限校验）
        chat_info_key = f"chat:info:{chat_id}"
        if not redis_client.exists(chat_info_key):
            return Response(
                {'error': '对话不存在'},
                status=status.HTTP_404_NOT_FOUND
            )

        # 验证用户归属
        stored_user_id = redis_client.hget(chat_info_key, 'user_id')
        print("stored_user_id: ", stored_user_id)
        print("user_id: ", user_id)
        if int(stored_user_id) != int(user_id):
            return Response(
                {'error': '无权限访问该对话'},
                status=status.HTTP_403_FORBIDDEN
            )

        # 验证对话状态
        if redis_client.hget(chat_info_key, 'status') != 'active':
            return Response(
                {'error': '对话已删除'},
                status=status.HTTP_404_NOT_FOUND
            )

        # 4. 获取对话基础信息
        chat_info = redis_client.hgetall(chat_info_key)
        create_time = datetime.fromtimestamp(
            chat_info.get('create_time', 0) / 1000
        ).strftime('%Y-%m-%d %H:%M:%S')

        last_msg_time = datetime.fromtimestamp(
            chat_info.get('last_msg_time', 0) / 1000
        ).strftime('%Y-%m-%d %H:%M:%S')

        # 5. 获取对话消息列表
        chat_msgs_key = f"chat:msgs:{chat_id}"
        msg_ids = redis_client.lrange(chat_msgs_key, 0, -1)
        messages = []

        for msg_id in msg_ids:
            if not msg_id:  # 过滤初始化的空值
                continue

            msg_key = f"chat:msg:{msg_id}"
            msg_info = redis_client.hgetall(msg_key)
            if not msg_info:
                continue

            # 格式化消息数据
            send_time = datetime.fromtimestamp(
                msg_info.get('send_time', 0) / 1000
            ).strftime('%Y-%m-%d %H:%M:%S')

            messages.append({
                'msg_id': msg_id,
                'question': msg_info.get('question', ''),
                'answer': msg_info.get('answer', ''),
                'is_continue': bool(msg_info.get('parent_msg_id')),
                'parent_msg_id': msg_info.get('parent_msg_id', ''),
                'send_time': send_time,
                'status': msg_info.get('status', 'fail')
            })

        # 6. 返回结果
        return Response({
            'chat_info': {
                'chat_id': chat_id,
                'title': chat_info.get('title', '未命名对话'),
                'create_time': create_time,
                'last_msg_time': last_msg_time
            },
            'messages': messages
        })


class SendMessageView(APIView):
    """发送消息接口"""

    def post(self, request):
        # 1. 获取参数
        user_id = request.data.get('user_id')
        chat_id = request.data.get('chat_id')
        question = request.data.get('question')
        parent_msg_id = request.data.get('parent_msg_id', '')

        # 2. 参数校验
        if not all([user_id, chat_id, question]):
            return Response(
                {'error': 'user_id、chat_id、question不能为空'},
                status=status.HTTP_400_BAD_REQUEST
            )

        if len(question) > 2000:
            return Response(
                {'error': '问题长度不能超过2000字'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # 3. 验证对话有效性
        chat_info_key = f"chat:info:{chat_id}"
        if not redis_client.exists(chat_info_key):
            return Response(
                {'error': '对话不存在'},
                status=status.HTTP_404_NOT_FOUND
            )

        if redis_client.hget(chat_info_key, 'user_id') != user_id:
            return Response(
                {'error': '无权限访问该对话'},
                status=status.HTTP_403_FORBIDDEN
            )

        # 4. 验证父消息（如果存在）
        if parent_msg_id:
            parent_msg_key = f"chat:msg:{parent_msg_id}"
            if not redis_client.exists(parent_msg_key):
                return Response(
                    {'error': '父消息不存在'},
                    status=status.HTTP_404_NOT_FOUND
                )
            if redis_client.hget(parent_msg_key, 'chat_id') != chat_id:
                return Response(
                    {'error': '父消息不属于当前对话'},
                    status=status.HTTP_400_BAD_REQUEST
                )

        # 5. 调用通义千问API（示例实现）
        try:
            # 实际项目中替换为真实API调用
            # 这里仅做示例
            answer = f"这是对问题「{question}」的回答（模拟通义千问返回）"
            model_version = "qwen-turbo"
            status = "success"
            error_msg = ""
        except Exception as e:
            answer = ""
            model_version = ""
            status = "fail"
            error_msg = str(e)

        # 6. 生成消息ID
        timestamp = int(time.time() * 1000)
        random_str = uuid.uuid4().hex[:2]
        msg_id = f"msg_{chat_id}_{timestamp}_{random_str}"

        # 7. 存储消息（业务逻辑：定义键名和存储结构）
        now_ts = timestamp
        # 存储消息详情
        msg_key = f"chat:msg:{msg_id}"
        redis_client.hset(msg_key, 'chat_id', chat_id)
        redis_client.hset(msg_key, 'user_id', user_id)
        redis_client.hset(msg_key, 'question', question)
        redis_client.hset(msg_key, 'answer', answer)
        redis_client.hset(msg_key, 'parent_msg_id', parent_msg_id)
        redis_client.hset(msg_key, 'send_time', now_ts)
        redis_client.hset(msg_key, 'status', status)
        redis_client.hset(msg_key, 'error_msg', error_msg)
        redis_client.hset(msg_key, 'model_version', model_version)
        redis_client.expire(msg_key, 30 * 24 * 3600)

        # 添加消息ID到对话列表
        chat_msgs_key = f"chat:msgs:{chat_id}"
        redis_client.rpush(chat_msgs_key, msg_id)

        # 更新对话最后消息时间
        redis_client.hset(chat_info_key, 'last_msg_time', now_ts)

        # 更新用户对话列表排序
        user_chat_key = f"chat:user:list:{user_id}"
        redis_client.zadd(user_chat_key, {chat_id: now_ts})

        # 8. 返回结果
        return Response({
            'msg_id': msg_id,
            'question': question,
            'answer': answer,
            'send_time': datetime.fromtimestamp(now_ts / 1000).strftime('%Y-%m-%d %H:%M:%S'),
            'status': status
        })
